package com.eland.oa.main.model;

import org.directwebremoting.annotations.DataTransferObject;
import org.directwebremoting.annotations.RemoteProperty;

import com.eland.oa.main.constant.ELOpCode;
import com.eland.oa.main.constant.ELOpMessage;

@DataTransferObject
public class ELOpRtnPack {

	public static final String UNKNOWN_RTN_CODE = "U_xxxx_xxx";
	public static final String UNKNOWN_RTN_MSG = "系统无法确定操作的结果。";
	
	public static final String OP_CODE_DIMENSION_DELIM = "_";
	public static final String OP_RTN_TYPE_ACRN_PLAIN = "P";
	public static final String OP_RTN_TYPE_ACRN_ERROR = "E";
	public static final String OP_RTN_TYPE_ACRN_SUCCESS = "S";
	public static final String OP_RTN_TYPE_ACRN_WARNING = "W";
	
	@RemoteProperty private String returnCode;
	@RemoteProperty private String returnMessage;
	@RemoteProperty private Object returnObject;
	private Integer rtnTypeIdx;
	private Integer rtnOpIdx;
	private Integer rtnCodeIdx;
	
	public ELOpRtnPack() {
		
	}
	
	public ELOpRtnPack(Integer rtnTypeIdx, Integer rtnOpIdx, Integer rtnCodeIdx) {
		//Range check on type and operation
		if (rtnTypeIdx < ELOpCode.TYP_MIN ||
				rtnTypeIdx > ELOpCode.TYP_MAX ||
				rtnOpIdx < ELOpCode.OP_MIN ||
				rtnOpIdx > ELOpCode.OP_MAX ||
				rtnCodeIdx < 0 ||
				rtnCodeIdx >= ELOpMessage.EL_OP_MSG[rtnTypeIdx][rtnOpIdx].length)
		{
			this.setUnknownPack();
		} else {
			this.setReturnCode(resolveReturnCode(rtnTypeIdx, rtnOpIdx, rtnCodeIdx));
			this.setReturnMessage(ELOpMessage.EL_OP_MSG[rtnTypeIdx][rtnOpIdx][rtnCodeIdx]);
		}
	}

	private void setUnknownPack() {
		this.setReturnCode(UNKNOWN_RTN_CODE);
		this.setReturnMessage(UNKNOWN_RTN_MSG);
	}
	
	public static String resolveReturnCode(Integer rtnTypeIdx, Integer rtnOpIdx, Integer rtnCodeIdx) {
		/* Format a return code
		 * 1. Type will be tagged as P(Plain), E(Error), S(Success), W(Warning)
		 * 2. Operation will be padded to 4 digits
		 * 3. Return Code will be padded to 3 digits
		 * The 3 dimensions are linked with '_'.
		 * Total length of the operation code is 10
		 */
		String d1 = "", d2 = "", d3 = "";		//3 dimensions
		
		//Dimension 1
		if (rtnTypeIdx == ELOpCode.TYP_PLAIN)
			d1 = OP_RTN_TYPE_ACRN_PLAIN;
		else if (rtnTypeIdx == ELOpCode.TYP_ERROR)
			d1 = OP_RTN_TYPE_ACRN_ERROR;
		else if (rtnTypeIdx == ELOpCode.TYP_WARNING)
			d1 = OP_RTN_TYPE_ACRN_WARNING;
		else if (rtnTypeIdx == ELOpCode.TYP_SUCCESS)
			d1 = OP_RTN_TYPE_ACRN_SUCCESS;
		
		//Dimension 2
		d2 = String.format("%04d", rtnOpIdx);
		
		//Dimension 3
		d3 = String.format("%03d", rtnCodeIdx);
		
		return d1 + OP_CODE_DIMENSION_DELIM + d2 + OP_CODE_DIMENSION_DELIM + d3;
	}
	
	public static String resolveReturnMessage(String returnCode) {
		String s1; 
		Integer d1, d2, d3;
		String[] array = returnCode.split(OP_CODE_DIMENSION_DELIM);
		
		try {
			//dimension 1
			s1 = array[0];
			if (s1.equals(OP_RTN_TYPE_ACRN_PLAIN))
				d1 = ELOpCode.TYP_PLAIN;
			else if (s1.equals(OP_RTN_TYPE_ACRN_ERROR))
				d1 = ELOpCode.TYP_ERROR;
			else if (s1.equals(OP_RTN_TYPE_ACRN_WARNING))
				d1 = ELOpCode.TYP_WARNING;
			else if (s1.equals(OP_RTN_TYPE_ACRN_SUCCESS))
				d1 = ELOpCode.TYP_SUCCESS;
			else
				return UNKNOWN_RTN_MSG;
			
			//dimension 2
			d2 = Integer.parseInt(array[1]);
			if (d2 < ELOpCode.OP_MIN || d2 > ELOpCode.OP_MAX)
				return UNKNOWN_RTN_MSG;
			
			//dimension 3
			d3 = Integer.parseInt(array[2]);
			if (d3 < 0 || d3 >= ELOpMessage.EL_OP_MSG[d1][d2].length)
				return UNKNOWN_RTN_MSG;
			
			return ELOpMessage.EL_OP_MSG[d1][d2][d3];
		} catch (Exception e) {
			return UNKNOWN_RTN_MSG;
		}
	}
	
	public String getReturnCode() {
		return returnCode;
	}

	public void setReturnCode(String returnCode) {
		this.returnCode = returnCode;
	}

	public String getReturnMessage() {
		return returnMessage;
	}

	public void setReturnMessage(String returnMessage) {
		this.returnMessage = returnMessage;
	}

	public Integer getRtnTypeIdx() {
		return rtnTypeIdx;
	}

	public void setRtnTypeIdx(Integer rtnTypeIdx) {
		this.rtnTypeIdx = rtnTypeIdx;
	}

	public Integer getRtnOpIdx() {
		return rtnOpIdx;
	}

	public void setRtnOpIdx(Integer rtnOpIdx) {
		this.rtnOpIdx = rtnOpIdx;
	}

	public Integer getRtnCodeIdx() {
		return rtnCodeIdx;
	}

	public void setRtnCodeIdx(Integer rtnCodeIdx) {
		this.rtnCodeIdx = rtnCodeIdx;
	}

	public Object getReturnObject() {
		return returnObject;
	}

	public void setReturnObject(Object returnObject) {
		this.returnObject = returnObject;
	}
}
